﻿#include <iostream>

#include <CommonUnits/CommonUnits.h>
#include <CommonUnits/UnitLists.h>
#include <CommonUnits/Units/Chrono.h>
#include <CommonUnits/Units/Frequency.h>
#include <CommonUnits/Version.h>
#include <format>

int main(int argc, char* argv[])
{
    CU::Kilohertz khz(1000);
    CU::Hertz hz(1000);
    std::cout << "khz:\t" << khz << std::endl;
    std::cout << "hz:\t" << hz << std::endl;
    std::cout << "CU::commonUnitsCast<CU::Hertz>(khz):\t" << CU::commonUnitsCast<CU::Hertz>(khz) << std::endl;
    std::cout << "khz + khz:\t" << khz + khz << std::endl;
    std::cout << "khz - hz:\t" << khz - hz << std::endl;
    std::cout << "khz + hz:\t" << khz + hz << std::endl;
    std::cout << "+khz:\t" << +khz << std::endl;
    std::cout << "-khz:\t" << -khz << std::endl;
    std::cout << "khz / hz:\t" << khz / hz << std::endl;
    std::cout << "khz / 5:\t" << khz / 5 << std::endl;
    std::cout << "khz * 5:\t" << khz * 5 << std::endl;
    khz += hz;
    std::cout << "khz += hz:\t" << khz << std::endl;
    khz -= hz;
    std::cout << "khz -= hz:\t" << khz << std::endl;
    khz *= 10;
    std::cout << "khz *= 10:\t" << khz << std::endl;
    khz /= 10;
    std::cout << "khz /= 10:\t" << khz << std::endl;
    khz = 10 * hz;
    std::cout << "khz = 10 * hz:\t" << khz << std::endl;
    std::cout << "CU::Kilohertz(1) == CU::Hertz(1E3):\t" << (CU::Kilohertz(1) == CU::Hertz(1E3)) << std::endl;
    std::cout << "CU::Kilohertz(2) == CU::Hertz(1E3):\t" << (CU::Kilohertz(2) == CU::Hertz(1E3)) << std::endl;
    std::cout << "CU::Kilohertz(1) != CU::Hertz(1E3):\t" << (CU::Kilohertz(1) != CU::Hertz(1E3)) << std::endl;
    std::cout << "CU::Kilohertz(2) != CU::Hertz(1E3):\t" << (CU::Kilohertz(2) != CU::Hertz(1E3)) << std::endl;
    std::cout << "CU::Kilohertz(2) > CU::Hertz(1E3):\t" << (CU::Kilohertz(2) > CU::Hertz(1E3)) << std::endl;
    std::cout << "CU::Kilohertz(2) < CU::Hertz(1E3):\t" << (CU::Kilohertz(2) < CU::Hertz(1E3)) << std::endl;
    std::string dest = static_cast<std::string>(khz);
    std::cout << "std::string dest = khz:\t" << dest << std::endl;
    static_assert(std::is_same_v<CU::UnitListElementType<0, CU::Frequency::Units::FrequencyList>, CU::Frequency::Units::Hz>);
    std::cout << "CU::Units::FrequencyList::count:\t" << CU::Frequency::Units::FrequencyList::count << std::endl;
    std::cout << "CU::visitUnitList<CU::Units::FrequencyList>([](const std::string_view& unit, std::intmax_t num, std::intmax_t den):"
              << std::endl;
    CU::visitUnitList<CU::Chrono::Units::ChronoList>(
        [](const std::string_view& unit, std::intmax_t num, std::intmax_t den)
        {
            std::cout << unit << " num:" << num << " den:" << den << std::endl;
            return false;
        });
    std::cout << "CU::toUnit<CU::Megahertz>(1000, CU::Units::KHz::unit.data()):\t"
              << CU::Frequency::toUnit<CU::Megahertz>(1000, CU::Frequency::Units::kHz::unit.data()) << std::endl;
    std::cout << "CU::Seconds(std::chrono::milliseconds(1)):\t" << CU::Seconds(std::chrono::milliseconds(1)) << std::endl;
    std::cout << "CU::Seconds(std::chrono::seconds(2000)):\t" << CU::Seconds(std::chrono::seconds(2000)) << std::endl;
    std::cout << "CU::Seconds(std::chrono::days(1)):\t" << CU::Seconds(std::chrono::days(1)) << std::endl;
    std::cout << "CU::Seconds(std::chrono::years(1)):\t" << CU::Seconds(std::chrono::years(1)) << std::endl;
    auto func = [](const CU::Hertz& hz) { std::cout << hz << std::endl; };
    std::cout << "func(CU::Megahertz(100)):\t";
    func(CU::Megahertz(100));
    std::cout << "std::format(\"{}\", CU::Seconds(1)):\t" << std::format("{}", CU::Hertz(1)) << std::endl;
    auto seconds = CU::commonUnitsCast<CU::Seconds>(CU::Milliseconds(1));
    std::cout << COMMONUNITS_VERSION << std::endl;
    std::cout << "CU::Seconds(1) == CU::Milliseconds(1E3)\t" << (CU::Seconds(1E-7) == CU::Nanoseconds(1E2)) << std::endl;
    std::cout << CU::Chrono::toUnit<CU::Seconds>(1.0, "ms") << std::endl;
    std::cout << CU::Chrono::toUnit<CU::Milliseconds>(1.0, "s") << std::endl;
    std::cout << static_cast<std::chrono::milliseconds>(CU::Seconds(2.0)) << std::endl;
    return 0;
}
